package com.pan.script.pantrans;

import com.pan.script.ScriptTranslators;
import com.pan.script.pantrans.action.Action;
import com.pan.script.pantrans.action.impl.*;
import com.pan.script.pantrans.error.TransCompileError;
import com.pan.script.pantrans.sentence.Sentence;
import com.pan.script.pantrans.sentence.impl.ArgSentence;
import com.pan.script.pantrans.sentence.impl.LoopSentence;
import com.pan.script.pantrans.util.KeyEventMap;
import com.pan.script.pantrans.util.MouseEventMap;
import com.pan.exe.Executive;

import java.awt.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.function.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 一个解释器
 */
public class PanScriptTranslators implements ScriptTranslators {

    private HashMap<Integer, Consumer<Robot>> sentenceMap;
    private KeyEventMap keyEventMap;
    private MouseEventMap mouseEventMap;
    {
        sentenceMap = new HashMap<>();
        keyEventMap = KeyEventMap.INSTANCE;
        mouseEventMap = MouseEventMap.INSTANCE;
    }



    private String clear(String line) {
        int i = line.indexOf("//");
        if (i == -1) {
            return line.trim();
        } else {
            return line.substring(0, i).trim();
        }
    }

    private Pattern delayPattern = Pattern.compile("^delay\\s*:\\s*(\\d+)$");

    private Pattern downMousePattern = Pattern.compile("^down\\s+mouse\\s*:\\s*([1-3])$");
    private Pattern upMousePattern = Pattern.compile("^up\\s+mouse\\s*:\\s*([1-3])$");


    private Pattern downKeyPattern = Pattern.compile("^down\\s+key\\s*:\\s*(\\S+)$");
    private Pattern upKeyPattern = Pattern.compile("^up\\s+key\\s*:\\s*(\\S+)$");

    private Pattern clickPattern = Pattern.compile("^(up|down)\\s+(mouse|key)\\s*:\\s*(\\S+)$");

    private Pattern mouseMovePattern = Pattern.compile("^mouse-move\\s*:\\s*(\\d+)\\s*,\\s*(\\d+)$");
    private Pattern mouseScrollPattern = Pattern.compile("^mouse-scroll\\s*:\\s*(-?\\d+)$");

    private Pattern loopPattern = Pattern.compile("^loop\\s*(\\d+)\\s*:$");
    private Pattern endPattern = Pattern.compile("^loop\\s+end$");

    private Action delayAction = new DelayAction();

    private Action upMouseAction = new UpMouseAction();
    private Action downMouseAction = new DownMouseAction();

    private Action upKeyAction = new UpKeyAction();
    private Action downKeyAction = new DownKeyAction();

    private Action scollAction = new ScrollAction();

    private Action moveAction = new MouseMoveAction();


    public List<Sentence> toSentences(String[] lines){
        int lineOrder = 0;

        LinkedList<LinkedList<Sentence>> sentenceListStack = new LinkedList<>();
        Consumer<LinkedList<Sentence>> stackAdd = (sentence) -> sentenceListStack.addLast(sentence);
        Supplier<LinkedList<Sentence>> stackPop = () -> sentenceListStack.removeLast();
        Supplier<LinkedList<Sentence>> stackPeek = () -> sentenceListStack.peekLast();

        stackAdd.accept(new LinkedList<>());

        for (String line : lines) {
            line = clear(line);

            if (line.length() == 0) {
                //如果长度为 0 就跳过
                continue;
            }if (delayPattern.matcher(line).matches()) {
                //延迟
                Matcher matcher = delayPattern.matcher(line);
                matcher.find();
                int delayMs = Integer.parseInt(matcher.group(1));
                ArgSentence<Object> delaySentence = new ArgSentence(delayAction,delayMs);
                stackPeek.get().addLast(delaySentence);
            } else if (downMousePattern.matcher(line).matches()) {
                //按下鼠标
                Matcher matcher = downMousePattern.matcher(line);
                matcher.find();
                String mouseKey = matcher.group(1);
                Integer eventId = mouseEventMap.getEventId(mouseKey);
                stackPeek.get().addLast(new ArgSentence(downMouseAction,eventId));
            } else if (upMousePattern.matcher(line).matches()) {
                //释放鼠标
                Matcher matcher = upMousePattern.matcher(line);
                matcher.find();
                String mouseKey = matcher.group(1);
                Integer eventId = mouseEventMap.getEventId(mouseKey);
                stackPeek.get().addLast(new ArgSentence(upMouseAction,eventId));
            } else if (downKeyPattern.matcher(line).matches()){
                //按下键盘
                Matcher matcher = downKeyPattern.matcher(line);
                matcher.find();
                String key = matcher.group(1);
                Integer eventId = keyEventMap.getEventId(key);
                stackPeek.get().addLast(new ArgSentence<>(downKeyAction, eventId));
            } else if (upKeyPattern.matcher(line).matches()){
                //释放键盘
                Matcher matcher = upKeyPattern.matcher(line);
                matcher.find();
                String key = matcher.group(1);
                Integer eventId = keyEventMap.getEventId(key);
                stackPeek.get().addLast(new ArgSentence<>(upKeyAction, eventId));
            } else if (mouseScrollPattern.matcher(line).matches()){
                //滚动
                Matcher matcher = mouseScrollPattern.matcher(line);
                matcher.find();
                int scrollLength = Integer.parseInt(matcher.group(1));
                stackPeek.get().addLast(new ArgSentence<>(scollAction, scrollLength));
            }else if (mouseMovePattern.matcher(line).matches()){
                //鼠标移动
                Matcher matcher = mouseMovePattern.matcher(line);
                matcher.find();
                int x = Integer.parseInt(matcher.group(1));
                int y = Integer.parseInt(matcher.group(2));
                stackPeek.get().addLast(new ArgSentence<>(moveAction, new int[]{x,y}));
            } else if (loopPattern.matcher(line).matches()) {
                //循环
                Matcher matcher = loopPattern.matcher(line);
                matcher.find();
                int i = Integer.parseInt(matcher.group(1));
                stackPeek.get().addLast(new LoopSentence(i));
                stackAdd.accept(new LinkedList<>());
            } else if (endPattern.matcher(line).matches()) {
                //结束循环
                List<Sentence> innerSentences = stackPop.get();
                LinkedList<Sentence> lastList = stackPeek.get();
                Sentence lastSentence = lastList.peekLast();
                if (!(lastSentence instanceof LoopSentence)){
                    //如果loop end异常就报错
                    throw new TransCompileError(lineOrder,line,"意外的循环结束");
                }else {
                    ((LoopSentence)lastSentence).setSentenceList(innerSentences);
                }
            } else {
                throw new TransCompileError(lineOrder,line,"不认识的语句");
            }
            lineOrder++;
        }
        if (sentenceListStack.size() != 1){
            throw  new TransCompileError(lineOrder,"","脚本结构错误");
        }else {
            return sentenceListStack.removeLast();
        }
    }
    @Override
    public Executive to(String[] lines) {
        List<Sentence> sentences = toSentences(lines);
        Executive result = (robot) -> {
            //debug
            int line = 0;
            for (Sentence sentence : sentences) {
                sentence.execute(robot);
            }
        };
        return result;
    }
}
